<template>
    <van-popup
        v-model:show="showPopup" position="bottom" round :style="{ height: '90%' }" @opened="onPopupOpened"
        @closed="onPopupClosed"
    >
        <div class="muti-level-city-selector-container">
            <div class="fe-title">
                <h3>{{ type === 1 ? '按省市选择城市' : type === 2 ? '按级别选择城市' : '选择电商行为标签' }}</h3>
                <img src="@/assets/img/close-popup.png" alt="" @click="onPopupClosed" />
            </div>
            <div class="fe-search">
                <van-search
                    ref="searchRef" v-model="search" :placeholder="type === 3 ? '请输入类目关键字搜索' : '请输入城市名称或拼音'"
                    input-align="left" enterkeyhint="search" @search="onSearch" @clear="onClear"
                >
                    <template #left-icon>
                        <span class="icon iconfont icon-sousuo"></span>
                    </template>
                </van-search>
            </div>

            <div class="fe-selector">
                <div class="city-container">
                    <div class="fe-province-list">
                        <div
                            v-for="parent in treeData" :key="parent.id" class="fe-province-item"
                            :class="focusParent.id && (focusParent.id === parent.id) && 'checked'"
                            @click="selectParent(parent)"
                        >
                            <div class="check-container">
                                <span
                                    :class="[
                                        'icon iconfont',
                                        { 'icon-gouxuan-weixuan': !parent.isCheck && !parent.isIndeterminate },
                                        { 'icon-danxuan-xuanzhong': parent.isCheck },
                                        { 'icon-banxuanzhuangtai': parent.isIndeterminate },
                                    ]" @click="checkItem(parent)"
                                ></span>
                            </div>
                            <span class="label">{{ parent.name }}</span>
                        </div>
                    </div>
                    <div ref="cityListRef" class="fe-city-list">
                        <div v-for="child in focusParent.children" :key="child.id" class="fe-city-item" @click="checkItem(child)">
                            <div class="check-container">
                                <span
                                    :class="[
                                        'icon iconfont',
                                        { 'icon-gouxuan-weixuan': !child.isCheck },
                                        { 'icon-danxuan-xuanzhong': child.isCheck }
                                    ]"
                                ></span>
                            </div>
                            <span class="label">{{ child.name }}</span>
                        </div>
                    </div>
                </div>
            </div>

            <div class="fe-bottom">
                <div class="summary-count">
                    <div>
                        已选择<span class="count">{{ checkedList.length }}</span>个{{ type === 3 ? '类目' : '城市' }}
                    </div>
                    <span v-if="checkedList.length > 1" class="expand" @click="changeExpand">{{ showAllCheckedList ? '收起' :
                        '显示全部' }}</span>
                </div>
                <div v-if="checkedList?.length" class="checked-city-list" :class="!showAllCheckedList && 'retract'">
                    <div v-for="(city, index) in checkedList" :key="city.id" class="checked-city-item">
                        <span class="fe-label">{{ city.name }}</span>
                        <span class="icon iconfont icon-a-biaoqianshanchu" @click="clearCurrentItem(city, index)"></span>
                    </div>
                </div>
                <div class="fe-btns">
                    <div class="clear" @click="clearAll">
                        全部清空
                    </div>
                    <div class="confirm" @click="confirm">
                        确定
                    </div>
                </div>
            </div>
        </div>
    </van-popup>
</template>

<script lang="ts" setup>
import { ref, watch, PropType } from 'vue';
import { Toast, Popup as VanPopup, Search as VanSearch } from 'vant';
import { TreeChildModel, ReturnData } from './city.module';

const props = defineProps({
    // 展示popup
    show: {
        type: Boolean,
        require: true,
        default: false,
    },
    // 传入数据list
    list: {
        type: Array as PropType<TreeChildModel[]>,
        require: true,
        default: () => [],
    },
    // 1：按省市选择城市 2:按级别选择城市 3:选择电商行为标签
    type: {
        type: Number,
        require: true,
        default: 1,
    },
    // 选中的数据id集合
    selected: {
        type: Array as PropType<string[]>,
        require: false,
        default: () => [],
    },
    isRequire: {
        type: Boolean,
        require: false,
        default: true,
    },
});

const showPopup = ref(false);
const search = ref('');// 筛选关键字
const isFilterModel = ref(false);// 是否在筛选数据状态下
const treeData = ref<TreeChildModel[]>([]);// 页面展示的数据
const originTreeData = ref<TreeChildModel[]>([]);// 存放全部数据用于筛选
const focusParent = ref<TreeChildModel>({
    name: '',
    id: ''
});// 选中的父级元素
const showAllCheckedList = ref(false);// 是否展示底部全部选中数据
const checkedList = ref<TreeChildModel[]>([]);// 选中的二级数据集合
const cityListRef = ref<Element>();

const emit = defineEmits<{(e: 'close'): void; (e: 'confirm', value: ReturnData): void; }>();

function filterTree(arr: TreeChildModel[], keyword: string, first = true) {
    if (first) {// 首次传入深度克隆数据防止修改源数据
        // eslint-disable-next-line no-param-reassign
        arr = JSON.parse(JSON.stringify(arr)) as unknown as TreeChildModel[];
    }
    const emptyArr = [];
    for (const item of arr) {
        if (item.name.includes(keyword) || item.pinYin?.includes(keyword)) {
            emptyArr.push(item);
        } else if (item.children && Array.isArray(item.children) && item.children.length > 0) {
            item.children = filterTree(item.children, keyword, false);
            if (item.children.length) {
                emptyArr.push(item);
            }
        }
    }
    return emptyArr;
}

// 处理单个父级下子集选中状态
const handleChildCheckState = (parent: TreeChildModel, isJustHandleState?: boolean) => {
    if (parent.children?.length) {
        parent.isCheck = false;
        parent.isIndeterminate = false;
        const hasNoChecked = parent.children.every((child) => !child.isCheck);
        if (hasNoChecked) {
            return;
        }
        const isAllChecked = parent.children.every((child) => child.isCheck);
        if (isAllChecked) {
            parent.isCheck = true;
            if (!isJustHandleState) {
                checkedList.value = checkedList.value.concat(parent.children);
            }
            return;
        }
        parent.isIndeterminate = true;
        if (!isJustHandleState) {
            const checkArr = parent.children.filter((child) => child.isCheck);
            checkedList.value = checkedList.value.concat(checkArr);
        }
    }
};

// 按照选中的集合来重新赋值树形数据
const checkedData = (selectList: Array<string | TreeChildModel>, isNotInit?: boolean) => {
    originTreeData.value.forEach((parent: TreeChildModel) => {
        if (parent.children?.length) {
            parent.children.forEach((child: TreeChildModel) => {
                const item = (selectList || []).find((ele: string | TreeChildModel) => {
                    if (typeof ele === 'string') {
                        return ele === child.id;
                    }
                    return ele.id === child.id;
                });
                if (item) {
                    child.isCheck = true;
                } else {
                    child.isCheck = false;
                }
            });
            handleChildCheckState(parent, isNotInit);
        }
    });
};

// 统一处理数据选中状态和数据
const handleDataChecked = () => {
    if (isFilterModel.value) {
        treeData.value.forEach((parent: TreeChildModel) => {
            parent.children?.forEach(child => {
                const index = checkedList.value.findIndex(item => item.id === child.id);
                if (index > -1) {
                    checkedList.value.splice(index, 1);
                }
            });
            handleChildCheckState(parent);
        });
        checkedData(checkedList.value, true);
    } else {
        checkedList.value = [];
        originTreeData.value.forEach((parent: TreeChildModel) => {
            handleChildCheckState(parent);
        });
    }
};

// 处理子集的选中状态
const handleChildrenCheck = (parent: TreeChildModel, checked: boolean) => {
    parent.children?.forEach((child: TreeChildModel) => {
        child.isCheck = checked;
    });
};

// 当筛选时进入筛选模式并重新复制treeData和选中父级
const onSearch = () => {
    treeData.value = filterTree(originTreeData.value, search.value, true);
    if (treeData.value.length !== originTreeData.value.length) {
        isFilterModel.value = true;
    }

    // 把筛选后的数据更新一下选中状态
    treeData.value.forEach((parent: TreeChildModel) => {
        handleChildCheckState(parent, true);
    });
    // 选中筛选后的第一个父级
    focusParent.value = treeData.value.length ? treeData.value[0] : {
        name: '',
        id: ''
    };
};

const onClear = () => {
    checkedData(checkedList.value, true);
    treeData.value = originTreeData.value;
    treeData.value.length && (focusParent.value = treeData.value[0]);
};
const changeExpand = () => {
    showAllCheckedList.value = !showAllCheckedList.value;
};
const selectParent = (item: TreeChildModel) => {
    focusParent.value = item;
    cityListRef.value as unknown as Element;
    if (cityListRef.value) {
        cityListRef.value.scrollTop = 0;
    }
};

const checkItem = (item: TreeChildModel) => {
    item.isCheck = !item.isCheck;
    if (item.children?.length) {
        item.isIndeterminate = false;
        handleChildrenCheck(item, item.isCheck);
    }
    handleDataChecked();
};

const clearAll = () => {
    originTreeData.value.forEach(item => {
        item.isCheck = false;
        if (item.children?.length) {
            item.isIndeterminate = false;
            handleChildrenCheck(item, false);
        }
    });
    // 如果是在筛选模式下要清空筛选出来的数据选中状态
    if (isFilterModel.value) {
        treeData.value.forEach(item => {
            item.isCheck = false;
            if (item.children?.length) {
                item.isIndeterminate = false;
                handleChildrenCheck(item, false);
            }
        });
    }
    checkedList.value = [];
    showAllCheckedList.value = false;
};

// 删除当前选中
const clearCurrentItem = (item: TreeChildModel, index: number) => {
    item.isCheck = false;
    checkedList.value.splice(index, 1);
    handleDataChecked();
};

// 点击确定时把选中的项目emit出去
const confirm = () => {
    if (props.isRequire && !checkedList.value.length) {
        Toast.fail('请选择');
        return;
    }
    const data = {
        nameList: checkedList.value.map(item => item.name),
        selected: checkedList.value.map(item => item.id),
        checkedData: checkedList.value
    };
    emit('confirm', data);
    emit('close');
};

// 打开选择器处理传入数据
const initData = () => {
    treeData.value = JSON.parse(JSON.stringify(props.list)) as unknown as TreeChildModel[];
    originTreeData.value = treeData.value;

    treeData.value.length && (focusParent.value = treeData.value[0]);
    // 处理传入的选中项目
    if (props.selected.length) {
        checkedData(props.selected);
    }
};

const onPopupOpened = () => {
    initData();
};

// 关闭选择器清空筛选条件和选中项目
const onPopupClosed = () => {
    emit('close');
    search.value = '';
    checkedList.value = [];
    showAllCheckedList.value = false;
};

watch(
    () => props.show,
    (newVal) => {
        showPopup.value = newVal;
    }
);
</script>

<style scoped lang="scss">
.muti-level-city-selector-container {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 100%;

    .fe-title {
        display: flex;
        padding: 0 12px;
        margin-top: 20px;

        h3 {
            height: 22px;
            // font-family: PingFangSC-SNaNpxibold;
            font-weight: 600;
            font-size: 16px;
            color: #333333;
            text-align: center;
            flex: 1;
            margin-left: 20px;
        }

        img {
            width: 20px;
            height: 20px;
        }
    }

    .fe-search {
        margin-top: 12px;
        padding: 0 12px;

        .icon-sousuo {
            color: #bfbfbf;
            font-size: 16px;
            margin-right: 4px;
        }

        :deep(.van-search) {
            padding: 0;
        }

        :deep([class~="van-search__content"]) {
            border-radius: 6px;
            background: #f8f8f8;
        }
    }

    .fe-selector {
        margin-top: 12px;
        width: 100%;
        flex: 1;
        overflow: hidden;
        transition: all 0.5s;

        .city-container {
            display: flex;
            height: 100%;
        }

        .fe-province-list,
        .fe-city-list {
            width: 33.3%;
            align-self: stretch;
            overflow: auto;

            .fe-province-item,
            .fe-city-item {
                height: 48px;
                line-height: 48px;
                padding: 0 8px 0 14px;
                position: relative;
                display: flex;
                align-items: center;
                background: #f8f8f8;

                .check-container {
                    position: relative;
                }

                .iconfont {
                    width: 16px;
                    height: 16px;
                }

                .icon-gouxuan-weixuan {
                    color: #d2d2d2;
                }

                .icon-danxuan-xuanzhong {
                    color: #e60044;
                }

                .icon-banxuanzhuangtai {
                    color: #e60044;
                }

                .check-box {
                    display: inline-block;
                    width: 16px;
                    height: 16px;
                    border-radius: 50%;
                    border: 1px solid #cecece;
                    margin-right: 10px;
                    background: #ffffff;
                    position: absolute;
                    top: 50%;
                    transform: translate(0, -50%);
                }

                .label {
                    // font-family: PingFangSC-Regular;
                    font-weight: 400;
                    font-size: 14px;
                    color: #333333;
                    margin-left: 10px;
                    width: calc(100% - 24px);
                    display: inline-block;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }
            }

            .checked {
                background: #ffffff;
            }

            .checked::before {
                content: "";
                position: absolute;
                display: inline-block;
                width: 3px;
                height: 18px;
                background: #e60044;
                border-radius: 1px;
                left: 0;
            }

            .fe-city-item {
                background: #ffffff;
            }
        }
        .fe-city-list {
            width: 66.6%;
        }

        .fe-province-list {
            background: #f8f8f8;
        }
    }

    .fe-bottom {
        background: #ffffff;
        box-shadow: 0 -2px 4px 0 #ebebeb80;
        padding-top: 17px;
        padding-bottom: constant(safe-area-inset-bottom);
        padding-bottom: env(safe-area-inset-bottom);
        overflow: hidden;
        box-sizing: border-box;

        // padding: 17px 12px 0 14px;
        .summary-count {
            display: flex;
            justify-content: space-between;
            font-size: 14px;
            padding: 0 12px 0 14px;
            margin-bottom: 10px;

            span {
                display: inline-block;
            }

            .count {
                color: #e60044;
                margin: 0 5px;
                font-weight: bold;
            }

            .expand {
                color: #397ff8;
            }
        }

        .checked-city-list {
            display: flex;
            flex-wrap: wrap;
            max-height: 250px;
            overflow: auto;
            padding: 0 12px 0 14px;
            transition: all 0.5s;

            .checked-city-item {
                height: 30px;
                line-height: 30px;
                padding: 0 12px;
                background: #fafafa;
                border-radius: 6px;
                margin-right: 10px;
                margin-bottom: 10px;
            }

            .icon-a-biaoqianshanchu {
                display: inline-block;
                color: #848484;
                font-size: 12px;
                transform: scale(0.67);
                margin-left: 8px;
            }
        }

        .retract {
            height: 40px;
            max-height: 40px;
            overflow: hidden;
        }

        .fe-btns {
            margin-top: 5px;
            border-top: 0.5px solid #f4f4f4;
            display: flex;
            padding: 6px 12px 8px 14px;

            .clear {
                width: 120px;
                height: 38px;
                line-height: 38px;
                background: #ffffff;
                border: 0.5px solid #d2d2d2;
                border-radius: 6px;
                // font-family: PingFangSC-Regular;
                font-weight: 400;
                font-size: 14px;
                color: #222222;
                text-align: center;
                margin-right: 13px;
            }

            .confirm {
                width: calc(100% - 120px);
                height: 38px;
                line-height: 38px;
                background: #e60044;
                border: 0.5px solid #e60044;
                border-radius: 6px;
                // font-family: PingFangSC-SNaNpxibold;
                font-weight: 600;
                font-size: 14px;
                color: #ffffff;
                text-align: center;
            }
        }
    }

    .list {
        height: 0;
        overflow: hidden;
        transition: height 0.5s;
    }

    .list-enter,
    .list-leave-to {
        height: 0;
    }

    .list-enter-active,
    .list-leave-active {
        transition: height 0.5s;
    }

    .list-enter-to,
    .list-leave {
        height: auto;
    }
}
</style>
